package org.cncy;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

public class HttpsXMLUtil {

    static final String charsetName = "UTF-8";

    private static final int PACKET_HEAD_COMMOND_LEN = 4;// 发送报文头，每一个字段长度
    static public final int NET_BUFFER_SIZE = 512;


    public static byte[] getXMLRequestByte(int command,String requestStr) {

        try {
            //
            return constructPackets(command, addHeaderLength(requestStr));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new byte[0];
    }

    public static String get3001ResponseStr(byte[] responseBytes) {

        try {
            String response = parseXmlContent(parseXmlBytes(responseBytes));
            return response;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }


    //=================================Request处理========================================

    public static byte[] constructPackets(int command, byte[] xml) throws IOException {
        // 包头：数据段共16个字节，每4个字节为一个字段（低位在前）
        PacketHead head = new PacketHead(1001, 0, 0, command);
        // 协议格式：16字节命令值 +加密加压后二进制的xml内容
        byte[] packetHeadBytes = getPacketHeadBytes(head);



       // System.out.println(Arrays.toString(packetHeadBytes));
       // System.out.println(Arrays.toString(xml));
        byte [] end = combineBytes(packetHeadBytes, xml);
       // System.out.println(Arrays.toString(end));
        //System.out.println(new String(end,"UTF-8"));
        return end;
    }

    private static byte[] addHeaderLength(String requestXml) throws UnsupportedEncodingException {
        byte[] xml;
        xml = requestXml.getBytes(charsetName);
        return combineBytes(int2Bytes(xml.length), xml);
    }


    private static byte[] getPacketHeadBytes(PacketHead packetHead) throws IOException {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        baos.write(int2Bytes(packetHead.protocolVer));
        baos.write(int2Bytes(packetHead.isCompress));
        baos.write(int2Bytes(packetHead.encrptType));
        baos.write(int2Bytes(packetHead.commandType));
        return baos.toByteArray();
    }


    static class PacketHead {
        public int commandType = 0;
        public int encrptType = 0;
        public int isCompress = 0;
        public int protocolVer = 0;

        public PacketHead(){

        }
        public PacketHead(int protocolVer, int isCompress, int encrptType, int commandType) {
            this.protocolVer = protocolVer;
            this.isCompress = isCompress;
            this.encrptType = encrptType;
            this.commandType = commandType;
        }
    }


    /**
     * 解析得到解压解密后的报文字节流
     *
     * @Create Date 2012-05-21
     *            待解析的报文
     * @return byte[] 解析后的报文内容;
     */
    public static byte[] parseXmlBytes(byte[] responseInfo) throws IOException {
        // 读取报文头结点之后的内容
        ByteArrayInputStream bin = new ByteArrayInputStream(responseInfo, PACKET_HEAD_COMMOND_LEN * 4,
                responseInfo.length);
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        int bytesRead = 0;
        byte buffer[] = new byte[NET_BUFFER_SIZE];
        while ((bytesRead = bin.read(buffer, 0, NET_BUFFER_SIZE)) != -1) {
            bout.write(buffer, 0, bytesRead);
        }
        byte[] xml = bout.toByteArray();
        bout.close();
        bin.close();
        return xml;
    }



    /**
     * 解析报文头
     *
     * @Create Date 2012-05-21
     * @param receiveInfo
     *            待解析报文
     * @Author Xulei
     * @return ;
     */

    private static PacketHead parseHeadfromPackets(byte[] receiveInfo) throws IOException {
        PacketHead head = new PacketHead();
        head.protocolVer = byte2Int(receiveInfo, 0, PACKET_HEAD_COMMOND_LEN);
        head.isCompress = byte2Int(receiveInfo, PACKET_HEAD_COMMOND_LEN, PACKET_HEAD_COMMOND_LEN * 2);
        head.encrptType = byte2Int(receiveInfo, PACKET_HEAD_COMMOND_LEN * 2, PACKET_HEAD_COMMOND_LEN * 3);
        head.commandType = byte2Int(receiveInfo, PACKET_HEAD_COMMOND_LEN * 3,
                PACKET_HEAD_COMMOND_LEN * 4);
        return head;
    }

    //=================================Response处理========================================

    /**
     * 解析报文字节流，得到报文内容
     *
     * @Create Date 2012-06-19
     * @param xml
     *            待解析的报文字节流
     * @Author Xulei
     * @return String 解析后的报文内容;
     */
    public static String parseXmlContent(byte[] xml) throws IOException {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();

        // 读取前四个字节，为XML长度
        for (int i = 0; i < PACKET_HEAD_COMMOND_LEN; i++)
            bout.write(xml[i]);


        int xmlLen = byte2Int(bout.toByteArray());


        bout.close();
        // 读取xml内容
        ByteArrayInputStream bin = new ByteArrayInputStream(xml, PACKET_HEAD_COMMOND_LEN, xmlLen);

        bout = new ByteArrayOutputStream();
        int bytesRead = 0;
        byte buffer[] = new byte[NET_BUFFER_SIZE];
        while ((bytesRead = bin.read(buffer, 0, NET_BUFFER_SIZE)) != -1) {
            bout.write(buffer, 0, bytesRead);
        }
        byte[] xmlContent = bout.toByteArray();
        bout.close();
        bin.close();
        return new String(xmlContent,"UTF-8");
    }



//    ======================Bytes 转换 相关==========================

    // 低位在前
    public static byte[] int2Bytes(int intValue) {
        byte[] b = new byte[4];
        for (int i = 0; i < 4; i++) {
            b[i] = (byte) (intValue >> 8 * i & 0xFF);
        }
        return b;
    }

    // 低位在前
    public static int byte2Int(byte[] b) {
        int temp;
        int result = 0;
        for (int i = 0; i < 4; i++) {
            temp = ((b[i] & 0xFF) << (8 * i));
            result |= temp;
        }
        return result;
    }

    public static int byte2Int(byte[] b, int start, int end) {
        int temp;
        int result = 0;

        for (int i = start; i < end; i++) {
            temp = ((b[i] & 0xFF) << (8 * (i - start)));
            result |= temp;
        }
        return result;
    }

    public static byte[] combineBytes(byte[] byte1, byte[] byte2) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int count;
        try {
            if (byte1 != null) {
                ByteArrayInputStream bins1 = new ByteArrayInputStream(byte1);
                byte[] buffer1 = new byte[1024];
                while ((count = bins1.read(buffer1)) != -1) {
                    baos.write(buffer1, 0, count);
                    baos.flush();
                }
            }
            if (byte2 != null) {
                ByteArrayInputStream bins2 = new ByteArrayInputStream(byte2);
                byte[] buffer2 = new byte[1024];
                while ((count = bins2.read(buffer2)) != -1) {
                    baos.write(buffer2, 0, count);
                    baos.flush();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return baos.toByteArray();
    }

}